package com.sina.rd.dsp.zookeeper;

import com.netflix.curator.framework.CuratorFramework;
import com.netflix.curator.framework.CuratorFrameworkFactory;
import com.netflix.curator.framework.api.CuratorWatcher;
import com.netflix.curator.retry.ExponentialBackoffRetry;
import com.netflix.curator.utils.EnsurePath;
import com.netflix.curator.utils.ZKPaths;
import org.apache.log4j.Logger;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.Watcher;

import java.util.List;

public class ZKProxy {
	private static final Logger LOG = Logger.getLogger(ZKProxy.class);

	private CuratorFramework curator;
	private int CONNECTION_TIMEOUT = 30000;
	private int RETRYNUM = 10;
	private int SLEEPTIME = 1000;

	public ZKProxy(String zkserver) {
		curator = CuratorFrameworkFactory.builder().connectString(zkserver).connectionTimeoutMs(CONNECTION_TIMEOUT)
				.retryPolicy(new ExponentialBackoffRetry(SLEEPTIME,RETRYNUM)).build();
		curator.start();
	}

    ///////////////////////////////////////////////////
    ///////////////////query & watch //////////////
    ///////////////////////////////////////////////////

    public boolean isExsit(String path){
        try {
            if(curator.checkExists().forPath(path)!=null)
                return true;
        } catch (Exception e) {
            LOG.error("check path ["+path+"] error");
            e.printStackTrace();
            return false;
        }
        return false;
    }

    public boolean isExsitAndWatch(String path,CuratorWatcher watcher){
        try {
            if(curator.checkExists().usingWatcher(watcher).forPath(path)!=null)
                return true;
        } catch (Exception e) {
            LOG.error("check path ["+path+"] error");
            e.printStackTrace();
            return false;
        }
        return false;
    }


    public List<String> listChildren(String path) {
		List<String> children = null;
		try {
			if(isExsit(path)){
				children = curator.getChildren().forPath(path);
				for(int i =0 ;i<children.size();i++){
					if(!path.equals("/")){
						children.set(i, path+"/"+children.get(i));
					}else{
						children.set(i, "/"+children.get(i));
					}
				}
			}
		} catch (InterruptedException e) {
			e.printStackTrace();
		} catch (KeeperException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return children;
	}

    public List<String> listChildrenAndWatch(String path,CuratorWatcher watcher){
        List<String> children=null;
        try {
            if(isExsit(path)){
                children=curator.getChildren().usingWatcher(watcher).forPath(path);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return children;
    }

	public String getData(String path){
		byte[] data = null;
		try {
			//测试是否必须
			if(curator.checkExists().forPath(path) != null){
				data = curator.getData().forPath(path);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		if(data!=null){
			return new String(data);
		}
		return null;
	}

    public String geDatatAndWatch(String path,CuratorWatcher watcher){
        byte[] data = null;
        try {
            //测试是否必须
            if(curator.checkExists().forPath(path) != null){
                data = curator.getData().usingWatcher(watcher).forPath(path);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        if(data!=null){
            return new String(data);
        }
        return null;
    }


    ///////////////////////////////////////////////////
    /////////////////// curd //////////////
    ///////////////////////////////////////////////////

	public boolean create(String path) {
		try {
            if(curator.checkExists().forPath(path) != null){
                return false;
            }
			EnsurePath ensurePath = new EnsurePath(path);
			ensurePath.ensure(curator.getZookeeperClient());
			
			ZKPaths.mkdirs(curator.getZookeeperClient().getZooKeeper(), path);
			
			ensurePath.ensure(curator.getZookeeperClient());
			if(curator.checkExists().forPath(path) != null){
				return true;
			}
		} catch (InterruptedException e) {
			e.printStackTrace();
		} catch (KeeperException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return false;
	}



	public boolean create(String path,byte[] data) {
		try {
			EnsurePath ensurePath = new EnsurePath(path);
			ensurePath.ensure(curator.getZookeeperClient());
			
			ZKPaths.mkdirs(curator.getZookeeperClient().getZooKeeper(), path);
			ensurePath.ensure(curator.getZookeeperClient());
			if(curator.checkExists().forPath(path) != null){
				curator.setData().forPath(path, data);
				return true;
			}
		} catch (InterruptedException e) {
			System.out.println(e);
			e.printStackTrace();
		} catch (KeeperException e) {
			System.out.println(e);
			e.printStackTrace();
		} catch (Exception e) {
			System.out.println(e);
			e.printStackTrace();
		}
		return false;
	}

	public boolean delete(String path) {
		try {
			curator.delete().forPath(path);
			if(curator.checkExists().forPath(path) == null){
				return true;
			}else {
                List<String> children=listChildren(path);
                if(children!=null&&!children.isEmpty()){
                    return false;
                }
            }
		} catch (Exception e) {
			e.printStackTrace();
		}
		return false;
	}
	
	public boolean deleteAll(String path) {
		try {
            List<String> children=listChildren(path);
			if(children!=null){
				for(String p:children){
					deleteAll(p);
				}
			}
			curator.delete().forPath(path);
			if(curator.checkExists().forPath(path) == null){
				return true;
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return false;
	}

	public boolean setData(String path,String data) {
		try {
			curator.setData().forPath(path, data.getBytes());
			return true;
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
	}
	
	public void close(){
		curator.close();
	}
	
	static void printList(List<String> list){
		for(String path : list){
			System.out.println(path);
		}
	}

	 public static void main(String[] args) {
		ZKProxy zkProxy = new ZKProxy("10.75.17.173:2181,10.75.17.174:2181,10.75.18.139:2181");
		
//		printList(zkProxy.list("/rediscluster/offline/476"));
		
//		System.out.println(zkProxy.deleteAll("/rediscluster/offline/476"));
		
		System.out.println(zkProxy.deleteAll("/test"));
	}
}
